﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace LinqToDB.Provider
{
    /// <summary>
    /// 表达式打印，用于输出表达式到控制台
    /// </summary>
    class ExpressionPrinter : ExpressionVisitor
    {
        public ExpressionPrinter()
        { }

        int m_intSpace = 0;
        void Begin(object blue, object white)
        { 
            for(int i=0;i<m_intSpace;i++)
            {
                Console.Write("  ");
            }
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.Write("{0} ", blue);
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("{0} ", white);
            m_intSpace++;
        }
        void End()
        {
            m_intSpace--;
        }

        internal override Expression VisitConstant(ConstantExpression c)
        {
            if (c.Value is ITable)
            {
                Begin("Table", ((ITable)c.Value));
                var r = base.VisitConstant(c);
                End();
                return r;
            }
            else
            {
                Begin("Constant", c.Value);
                var r = base.VisitConstant(c);
                End();
                return r;
            }
        }

        internal override Expression VisitMethodCall(MethodCallExpression m)
        {
            if (m.Method.DeclaringType == typeof(Queryable))
            {
                return VisitQueryableMethod(m);
            }

            Begin("MethodCall", m.Method.Name);
            var r = base.VisitMethodCall(m);
            End();
            return r;
        }

        internal override Expression VisitParameter(ParameterExpression p)
        {
            Begin("Parameter", p.Name);
            var r = base.VisitParameter(p);
            End();
            return r;
        }

        internal override NewExpression VisitNew(NewExpression nex)
        {
            Begin("New", nex.Constructor.DeclaringType.Name);
            var r = base.VisitNew(nex);
            End();
            return r;
        }
        internal override Expression VisitMemberAccess(MemberExpression m)
        {
            Begin("MemberAccess", m.Member.Name);
            var r = base.VisitMemberAccess(m);
            End();
            return r;
        }

        internal override Expression VisitBinary(BinaryExpression b)
        {
            Begin("Binary", b.NodeType);
            var r = base.VisitBinary(b);
            End();
            return r;
        }

        internal override Expression VisitUnary(UnaryExpression u)
        {
            if (u.NodeType == ExpressionType.Quote)
                return base.VisitUnary(u);

            Begin("Unary", u.NodeType);
            var r = base.VisitUnary(u);
            End();
            return r;
        }

        Expression VisitQueryableMethod(MethodCallExpression m)
        {
            Begin(m.Method.Name,null);
            var r = base.VisitMethodCall(m);
            End();
            return r;
        }

        Expression VisitSelect(MethodCallExpression m)
        {
            Begin(m.Method.Name, null);
            var r = base.VisitMethodCall(m);
            End();
            return r;
        }

    }
}
